﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class PipeLine
	{
		public PipeLine(Pipe pipe, double dLoad)
		{
			this.DragForce = 0.0;
			this.pipeElem = pipe;
			this.load = dLoad;
			this.InitPipeInfos();
		}

		public Pipe Element
		{
			get
			{
				return this.pipeElem;
			}
			set
			{
				this.pipeElem = value;
			}
		}

		public ElementId Id
		{
			get
			{
				return this.pipeElem.Id;
			}
		}

		public int DN
		{
			get
			{
				return this.dn;
			}
			set
			{
				this.dn = value;
			}
		}

		public double Flow
		{
			get
			{
				return this.flow;
			}
			set
			{
				this.flow = value;
			}
		}

		public double Resistance
		{
			get
			{
				return this.resistance;
			}
			set
			{
				this.resistance = value;
			}
		}

		public double ResistanceFrict
		{
			get
			{
				return this.resistanceFrict;
			}
			set
			{
				this.resistanceFrict = value;
			}
		}

		public double DragForce { get; set; }

		public double Length
		{
			get
			{
				return this.length;
			}
		}

		public double Load
		{
			get
			{
				return this.load;
			}
			set
			{
				this.load = value;
			}
		}

		public double Temperature
		{
			get
			{
				return this.temperture;
			}
			set
			{
				this.temperture = value;
			}
		}

		public double PressDynamic
		{
			get
			{
				return this.pressDynamic;
			}
		}

		public double Velocity
		{
			get
			{
				return this.velocity;
			}
		}

		private void InitPipeInfos()
		{
			this.dn = Convert.ToInt32(this.pipeElem.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble() * 304.8);
			this.innerDiameter = this.pipeElem.get_Parameter(BuiltInParameter.RBS_PIPE_INNER_DIAM_PARAM).AsDouble() * 304.8;
			this.length = this.pipeElem.get_Parameter(BuiltInParameter.CURVE_ELEM_LENGTH).AsDouble() * 304.8 / 1000.0;
		}

		public int CalcPipeDiameter(HYHeatingSystemOption option, int pipeDia = 0)
		{
			this.density = HeatingCalcTools.GetDensityByTemperature(this.temperture);
			this.flow = HeatingCalcTools.CalcFlowByLoad(this.load, (double)option.SupplyTemperature, (double)option.ReturnTemperature) / this.density;
			this.dn = ((pipeDia == 0) ? HeatingCalcTools.CalcPipeDiameter(this.pipeElem, this.flow, this.temperture, option) : pipeDia);
			Log.Info(new string[]
			{
				string.Format("{0} load = {1} flow = {2} dn = {3}", new object[]
				{
					this.Element.Id.IntegerValue,
					this.load,
					this.flow,
					this.dn
				})
			});
			return this.dn;
		}

		public double CalcResistance(double tempSupply, double tempBack)
		{
			Dictionary<int, double> pipeMepSize = HeatingCalcTools.GetPipeMepSize(this.pipeElem);
			this.innerDiameter = pipeMepSize[this.dn];
			this.velocity = this.flow / (2827.4333882308138 * Math.Pow(this.innerDiameter * 0.001, 2.0));
			this.pressDynamic = 0.5 * this.density * this.velocity * this.velocity;
			double kinematicViscosity = HeatingCalcTools.GetKinematicViscosity(this.temperture);
			double λ = HeatingCalcTools.CalcFrictionCoeffic(this.velocity, this.innerDiameter, 0.2, kinematicViscosity);
			this.resistanceFrict = HeatingCalcTools.CalcRm(this.velocity, this.innerDiameter, λ, this.density);
			this.resistance = this.resistanceFrict * this.length;
			this.DragForce = this.resistance;
			return this.resistance;
		}

		public void BackRevit()
		{
			if (this.pipeElem.Document.IsLinked)
			{
				SavePipe.Add(this);
				return;
			}
			this.SetPipeDiameter(this.pipeElem);
		}

		private void SetPipeDiameter(Pipe pipe)
		{
			Parameter parameter = pipe.GetParameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
			if (parameter != null)
			{
				parameter.Set((double)this.dn / 304.8);
			}
			ConnectorSetIterator connectorSetIterator = this.GetConnectors(this.pipeElem).ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (connector.IsConnected)
				{
					this.GetConnectConnector(connector).Radius = (double)this.dn / 304.8 / 2.0;
				}
			}
		}

		private ConnectorSet GetConnectors(Element element)
		{
			if (element == null)
			{
				return null;
			}
			FamilyInstance familyInstance = element as FamilyInstance;
			if (familyInstance != null && familyInstance.MEPModel != null)
			{
				return familyInstance.MEPModel.ConnectorManager.Connectors;
			}
			MEPSystem mepsystem = element as MEPSystem;
			if (mepsystem != null)
			{
				return mepsystem.ConnectorManager.Connectors;
			}
			MEPCurve mepcurve = element as MEPCurve;
			if (mepcurve != null)
			{
				return mepcurve.ConnectorManager.Connectors;
			}
			return null;
		}

		private Connector GetConnectConnector(Connector connector)
		{
			Connector result = null;
			if (connector != null && connector.IsConnected)
			{
				ConnectorSetIterator connectorSetIterator = connector.AllRefs.ForwardIterator();
				while (connectorSetIterator.MoveNext())
				{
					object obj = connectorSetIterator.Current;
					Connector connector2 = obj as Connector;
					if (connector2 != null && connector2.Owner.UniqueId != connector.Owner.UniqueId && ((int)connector2.ConnectorType == 1 || (int)connector2.ConnectorType == 2 || (int)connector2.ConnectorType == 19))
					{
						result = connector2;
						break;
					}
				}
			}
			return result;
		}

		private Pipe pipeElem;

		private int dn;

		private double innerDiameter;

		private double density;

		private double velocity;

		private double length;

		private double pressDynamic;

		private double flow;

		private double temperture = 60.0;

		private double resistanceFrict;

		private double resistance;

		private double load;
	}
}
